﻿using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Media;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;

namespace TuanHAPriest
{
    public partial class Classname
    {
        #region Attackable

        public bool Attackable(WoWUnit target)
        {
            if (ValidUnit(target) && target.Distance - target.BoundingRadius < 40 &&
                IsEnemy(target) && target.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        //prevent double ValidUnit Check
        public bool AttackableValid(WoWUnit target)
        {
            if (target.Distance - target.BoundingRadius < 40 && IsEnemy(target) &&
                target.InLineOfSpellSight)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region CastSpell

        public string LastCastSpell = "";
        public WoWUnit LastCastUnit;
        public DateTime LastCastTime = DateTime.Now;
        public DateTime LastUpdateMyLatency;

        public void CastSpell(string spellName, WoWUnit u)
        {
            if (u == null || !u.IsValid)
            {
                return;
            }

            while (GCDReady > DateTime.Now && !NoGCDSpells.Contains(spellName))
            {
            }

            SpellManager.Cast(spellName, u);

            Color colorlog;
            if (u == Me)
            {
                colorlog = Colors.GreenYellow;
            }
            else if (Me.CurrentTarget != null && u == Me.CurrentTarget)
            {
                colorlog = Colors.Red;
            }
            else
            {
                colorlog = Colors.Yellow;
            }

            //Prevent spamming
            if (LastCastUnit != u || spellName != LastCastSpell || LastCastTime + TimeSpan.FromMilliseconds(500) < Now)
            {
                string barTwo = "Mana: " + Math.Round(Me.ManaPercent);

                string unitName;
                if (u.IsPlayer)
                {
                    unitName = u.Class.ToString();
                }
                else
                {
                    unitName = u.Name;
                }
                Logging.Write(colorlog, DateTime.Now.ToString("ss:fff") + " - HP: " +
                                        Math.Round(Me.HealthPercent) + "% - " +
                                        barTwo + " - " +
                                        unitName + " - " + Math.Round(u.Distance) + "y - " +
                                        Math.Round(u.HealthPercent) + "% hp - " + spellName);
            }

            LastCastTime = DateTime.Now;
            LastCastSpell = spellName;
            LastCastUnit = u;

            TickMilisecond = DateTime.Now;

            if (!NoGCDSpells.Contains(spellName))
            {
                UpdateGCD();
            }

            if (LastUpdateMyLatency.AddMinutes(3) < DateTime.Now)
            {
                UpdateMyLatency();
                LastUpdateMyLatency = DateTime.Now;
            }
        }

        #endregion

        #region ConstantFace

        public void ConstantFace(WoWUnit unit)
        {
            if (!IsOverrideModeOn && !Me.IsSafelyFacing(unit))
            {
                WoWMovement.ConstantFace(unit.Guid);
            }
        }

        #endregion

        #region GCD

        public static DateTime GCDReady;

        //private void UpdateGCDEvent(object sender, LuaEventArgs raw)
        //{
        //    var args = raw.Args;
        //    var player = Convert.ToString(args[0]);

        //    // Not me ... Im out!
        //    if (player != "player")
        //    {
        //        return;
        //    }
        //    var spellID = Convert.ToInt32(args[4]);
        //    var spellName = WoWSpell.FromId(spellID).Name;

        //}

        public static void UpdateGCD()
        {
            GCDReady = DateTime.Now + SpellManager.Spells["Shadow Word: Pain"].CooldownTimeLeft;
        }

        public static bool GCDL()
        {
            return DateTime.Now + TimeSpan.FromMilliseconds(MyLatency) <= GCDReady;
        }

        //public static bool Casting()
        //{
        //    return Me.IsCasting && Me.CastingSpellId != 15407; //Mind Flay

        //}

        public static bool Casting()
        {
            if (Me.HasPendingSpell("Mass Dispel"))
            {
                return true;
            }

            if (Me.IsChanneling && Me.ChanneledCastingSpellId == 48045 &&
                Me.CurrentChannelTimeLeft.TotalMilliseconds > THSettings.Instance.MindSearClipping) //Mind Sear
            {
                //Logging.Write("Me.IsChanneling: " + Me.ChanneledSpell.Name + " ID: " + Me.ChanneledSpell.Id + " left " + Me.CurrentChannelTimeLeft.TotalMilliseconds);
                return true;
            }

            if (Me.IsChanneling && Me.ChanneledCastingSpellId == 48045 &&
                Me.CurrentChannelTimeLeft.TotalMilliseconds <= THSettings.Instance.MindSearClipping) //Mind Sear
            {
                //Logging.Write("Me.IsChanneling: " + Me.ChanneledSpell.Name + " ID: " + Me.ChanneledSpell.Id + " left " + Me.CurrentChannelTimeLeft.TotalMilliseconds);
                return false;
            }

            if (Me.IsChanneling && Me.ChanneledCastingSpellId == 15407) //Mind Flay
            {
                return false;
            }

            if (Me.IsCasting || Me.IsChanneling)
            {
                return true;
            }

            return false;
        }

        public static bool CastingorGCDL()
        {
            return Casting() || GCDL();
        }

        #endregion

        #region GetAsyncKeyState

        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        #endregion

        #region CountEnemyNeary

        private double CountEnemyNeary(WoWObject unitCenter, float distance)
        {
            return
                NearbyUnFriendlyUnits.Where(
                    unit =>
                    unitCenter.Location.Distance(unit.Location) <= distance &&
                    (unit.Combat || !Me.IsInInstance && unit.Name.Contains("Dummy")) &&
                    !unit.IsPet &&
                    (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember ||
                     !Me.IsInInstance && (unit.IsTargetingMeOrPet || unit.Name.Contains("Dummy")))).Aggregate
                    <WoWUnit, double>(0, (current, unit) => current + 1);
        }

        #endregion

        #region CountEnemyFromPoint

        //private double CountEnemyFromPoint(WoWPoint pointCenter, float radius)
        //{
        //    return
        //        NearbyUnFriendlyUnits.Where(
        //            unit =>
        //            pointCenter.Distance(unit.Location) <= radius &&
        //            unit.Combat).Aggregate
        //            <WoWUnit, double>(0, (current, unit) => current + 1);
        //}

        #endregion

        #region DebuffCCBreakonDamage

        public static string ListCCBreakonDamage =
            "[2637][Hibernate][3355][Freezing Trap Effect][19503][Scatter Shot][19386][Wyvern Sting][118][Polymorph][20066][Repentance][2094][Blind][1776][Gouge][6770][Sap][76780][Bind Elemental][6358][Seduction (Succubus)][115268][Mesmerize (Shivarra)]";

        public double DebuffCCBreakonDamage(WoWUnit target)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (target == null || !target.IsValid || !target.IsAlive)
                    return 0;

                WoWAura longestDebuff =
                    target.Debuffs.Values.Where(a => ListCCBreakonDamage.Contains("[" + a.SpellId + "]")).OrderBy(
                        a => a.TimeLeft).FirstOrDefault();

                if (longestDebuff == null)
                {
                    return 0;
                }
                return longestDebuff.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region GetAllMyAuras

        public DateTime LastGetAllMyAuras = DateTime.Now;

        public void DumpAuras()
        {
            if (LastGetAllMyAuras.AddSeconds(10) < DateTime.Now)
            {
                var i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.GetAllAuras())
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.GetAllAuras Name: " + aura.Name + " - SpellId: " + aura.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.Auras)
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.Auras - Name: " + aura.Value.Name + " - SpellId: " + aura.Value.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.ActiveAuras)
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.ActiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
                                  aura.Value.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                i = 1;
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");
                foreach (var aura in Me.PassiveAuras)
                {
                    Logging.Write(LogLevel.Diagnostic,
                                  i + ". Me.PassiveAuras - Name: " + aura.Value.Name + " - SpellId: " +
                                  aura.Value.SpellId);
                    i = i + 1;
                }
                Logging.Write(LogLevel.Diagnostic, "----------------------------------");

                LastGetAllMyAuras = DateTime.Now;
            }
        }

        #endregion

        #region UnitCascade

        public WoWUnit UnitCascade;

        private bool GetUnitCascade()
        {
            UnitCascade = null;
            UnitCascade = (from unit in NearbyUnFriendlyUnits
                           orderby unit.Distance descending
                           where !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                           where DebuffCCBreakonDamage(unit) <= 0
                           where Me.Combat && (unit.Combat || unit.Name.Contains("Dummy"))
                           //where unit != LastCastUnit
                           //Make sure dont aggro extra group
                           where Me.CurrentMap.IsDungeon && unit.IsTargetingMyPartyMember ||
                                 Me.CurrentMap.IsRaid && unit.IsTargetingMyRaidMember ||
                                 !Me.IsInInstance && (unit.IsTargetingMeOrPet || unit.Name.Contains("Dummy"))
                           where unit.ThreatInfo.RawPercent < 90
                           where Me.IsFacing(unit)
                           where unit.CurrentHealth > Me.MaxHealth*0.8 || unit.Name.Contains("Dummy")
                           where unit.InLineOfSpellSight
                           select unit).FirstOrDefault();
            return UnitCascade != null;
        }

        #endregion

        #region GetUnitHaloSafe;

        public WoWUnit UnitHaloSafe;

        private bool IsHaloSafe()
        {
            if(!THSettings.Instance.HaloSafeCheck)
            {
                return true;
            }

            UnitHaloSafe = null;
            UnitHaloSafe = (from unit in NearbyUnFriendlyUnits
                            //where Me.CurrentMap.IsDungeon || Me.CurrentMap.IsRaid
                            where Me.CurrentMap.IsDungeon && unit.IsTargetingMyPartyMember ||
                                  Me.CurrentMap.IsRaid && unit.IsTargetingMyRaidMember ||
                                  !Me.IsInInstance && (unit.IsTargetingMeOrPet || unit.Name.Contains("Dummy"))
                            where unit.Distance2D < 33
                            where unit.InLineOfSpellSight
                            where unit.InLineOfSight
                            select unit).FirstOrDefault();
            return UnitHaloSafe == null;
        }

        #endregion

        #region GetUnitSWD

        public WoWUnit UnitSWD;

        private bool GetUnitSWD()
        {
            UnitSWD = null;
            UnitSWD = (from unit in NearbyUnFriendlyUnits
                       where !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                       //where Me.IsFacing(unit)
                       where Me.Combat
                       //Make sure dont aggro extra group
                       where Me.CurrentMap.IsDungeon && unit.IsTargetingMyPartyMember ||
                             Me.CurrentMap.IsRaid && unit.IsTargetingMyRaidMember ||
                             !Me.IsInInstance && (unit.IsTargetingMeOrPet || unit.Name.Contains("Dummy"))
                       where unit.ThreatInfo.RawPercent < 90
                       where unit.HealthPercent <= 20
                       where unit.MaxHealth >= Me.MaxHealth*0.8
                       where unit.InLineOfSpellSight
                       select unit).FirstOrDefault();
            return UnitSWD != null;
        }

        #endregion

        #region GetUnitSWP

        public WoWUnit UnitSWP;

        private bool GetUnitSWP()
        {
            UnitSWP = null;
            UnitSWP = (from unit in NearbyUnFriendlyUnits
                       where !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                       where Me.Combat && (unit.Combat || !Me.IsInInstance && unit.Name.Contains("Dummy"))
                       //Make sure dont aggro extra group
                       where Me.CurrentMap.IsDungeon && unit.IsTargetingMyPartyMember ||
                             Me.CurrentMap.IsRaid && unit.IsTargetingMyRaidMember ||
                             !Me.IsInInstance && (unit.IsTargetingMeOrPet || unit.Name.Contains("Dummy"))
                       where unit.ThreatInfo.RawPercent < 90
                       where MyAuraTimeLeft("Shadow Word: Pain", unit) < THSettings.Instance.SWPRefresh
                       where unit.InLineOfSpellSight
                       select unit).FirstOrDefault();
            return UnitSWP != null;
        }

        #endregion

        #region GetUnitSWPMoving

        public WoWUnit UnitSWPMoving;

        private bool GetUnitSWPMoving()
        {
            UnitSWPMoving = null;
            UnitSWPMoving = (from unit in NearbyUnFriendlyUnits
                             where !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                             where Me.Combat && (unit.Combat || !Me.IsInInstance && unit.Name.Contains("Dummy"))
                             //Make sure dont aggro extra group
                             where Me.CurrentMap.IsDungeon && unit.IsTargetingMyPartyMember ||
                                   Me.CurrentMap.IsRaid && unit.IsTargetingMyRaidMember ||
                                   !Me.IsInInstance && (unit.IsTargetingMeOrPet || unit.Name.Contains("Dummy"))
                             where unit.ThreatInfo.RawPercent < 90
                             where unit.InLineOfSpellSight
                             orderby MyAuraTimeLeft("Shadow Word: Pain", unit) ascending
                             select unit).FirstOrDefault();
            return UnitSWPMoving != null;
        }

        #endregion

        #region GetUnitVT

        public WoWUnit UnitVT;

        private bool GetUnitVT()
        {
            UnitVT = null;
            UnitVT = (from unit in NearbyUnFriendlyUnits
                      where !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                      where Me.Combat && (unit.Combat || !Me.IsInInstance && unit.Name.Contains("Dummy"))
                      //where unit != LastCastUnit
                      //Make sure dont aggro extra group
                      where Me.CurrentMap.IsDungeon && unit.IsTargetingMyPartyMember ||
                            Me.CurrentMap.IsRaid && unit.IsTargetingMyRaidMember ||
                            !Me.IsInInstance && (unit.IsTargetingMeOrPet || unit.Name.Contains("Dummy"))
                      where unit.ThreatInfo.RawPercent < 90
                      where Me.IsFacing(unit)
                      where unit.CurrentHealth > Me.MaxHealth*2 || unit.Name.Contains("Dummy")
                      where MyAuraTimeLeft("Vampiric Touch", unit) < THSettings.Instance.VampiricTouchRefresh
                      where unit.InLineOfSpellSight
                      select unit).FirstOrDefault();
            return UnitVT != null;
        }

        #endregion

        #region GetUnitMindSear

        public WoWUnit UnitMindSear;

        private bool GetUnitMindSear()
        {
            UnitMindSear = null;
            UnitMindSear = (from unit in NearbyUnFriendlyUnits
                            where !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                            where Me.Combat
                            where unit.Combat
                            where !unit.IsFlying
                            where !unit.IsFalling
                            where Me.CurrentMap.IsDungeon && unit.IsTargetingMyPartyMember ||
                                  Me.CurrentMap.IsRaid && unit.IsTargetingMyRaidMember ||
                                  !Me.IsInInstance && (unit.IsTargetingMeOrPet || unit.Name.Contains("Dummy"))
                            where unit.ThreatInfo.RawPercent < 100
                            where CountEnemyNeary(unit, 10) >= 3
                            orderby CountEnemyNeary(unit, 10) descending
                            where unit.InLineOfSpellSight
                            select unit).FirstOrDefault();
            return UnitMindSear != null;
        }

        private bool GetUnitMindSear5()
        {
            UnitMindSear = null;
            UnitMindSear = (from unit in NearbyUnFriendlyUnits
                            where !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                            where Me.Combat && (unit.Combat || !Me.IsInInstance && unit.Name.Contains("Dummy"))
                            where !unit.IsFlying
                            where Me.CurrentMap.IsDungeon && unit.IsTargetingMyPartyMember ||
                                  Me.CurrentMap.IsRaid && unit.IsTargetingMyRaidMember ||
                                  !Me.IsInInstance && (unit.IsTargetingMeOrPet || unit.Name.Contains("Dummy"))
                            //where unit.ThreatInfo.RawPercent < 100
                            where CountEnemyNeary(unit, 10) >= THSettings.Instance.MindSearStartonUnit
                            orderby CountEnemyNeary(unit, 10) descending
                            where unit.InLineOfSpellSight
                            select unit).FirstOrDefault();
            //if (UnitMindSear != null)
            //{
            //    Logging.Write("UnitMindSear: " + UnitMindSear.Name);
            //}
            //else
            //{
            //    Logging.Write("UnitMindSear: Null");
            //}
            return UnitMindSear != null;
        }

        #endregion

        #region GetUnitLowThreat

        public WoWUnit UnitLowThreat;

        #endregion

        #region IndexToKeys

        public Keys KeyTwo;

        public Keys IndexToKeys(int index)
        {
            switch (index)
            {
                case 1:
                    return Keys.A;
                case 2:
                    return Keys.B;
                case 3:
                    return Keys.C;
                case 4:
                    return Keys.D;
                case 5:
                    return Keys.E;
                case 6:
                    return Keys.F;
                case 7:
                    return Keys.G;
                case 8:
                    return Keys.H;
                case 9:
                    return Keys.I;
                case 10:
                    return Keys.I;
                case 11:
                    return Keys.K;
                case 12:
                    return Keys.L;
                case 13:
                    return Keys.M;
                case 14:
                    return Keys.N;
                case 15:
                    return Keys.O;
                case 16:
                    return Keys.P;
                case 17:
                    return Keys.Q;
                case 18:
                    return Keys.R;
                case 19:
                    return Keys.S;
                case 20:
                    return Keys.T;
                case 21:
                    return Keys.U;
                case 22:
                    return Keys.V;
                case 23:
                    return Keys.W;
                case 24:
                    return Keys.X;
                case 25:
                    return Keys.Y;
                case 26:
                    return Keys.Z;
                case 27:
                    return Keys.Up;
                case 28:
                    return Keys.Down;
                case 29:
                    return Keys.Left;
                case 30:
                    return Keys.Right;
            }
            return Keys.None;
        }

        #endregion

        #region IsHealing

        //private static bool IsHealing()
        //{
        //    return Me.IsCasting &&
        //           (Me.CastingSpell.Name == "Flash of Light" || Me.CastingSpell.Name == "Divine Light" ||
        //            Me.CastingSpell.Name == "Holy Light" || Me.CastingSpell.Name == "Holy Radiance");
        //}

        #endregion

        #region IsAttacking

        //private static bool IsAttacking()
        //{
        //    return Me.IsCasting && Me.CastingSpell.Name == "Denounce";
        //}

        #endregion

        #region IsEnemy

        //public ulong RealGuid;

        //private static WoWPlayer GetUnitIsInMyPartyOrRaid(WoWUnit u)
        //{
        //    using (StyxWoW.Memory.AcquireFrame())
        //    {
        //        return (from unit in ObjectManager.GetObjectsOfType<WoWPlayer>(true, true)
        //                where unit.IsInMyPartyOrRaid
        //                //|| unit.IsMe && (!Me.IsInParty || !Me.IsInRaid)
        //                where unit.Guid == u.Guid || unit.Guid == u.CreatedByUnitGuid
        //                select unit).FirstOrDefault();
        //    }
        //}


        public bool IsEnemy(WoWUnit target)
        {
            if (target == null)
            {
                return false;
            }

            if (!target.IsFriendly || target.Name.Contains("Dummy") && target.IsWithinMeleeRange)
            {
                return true;
            }
            return false;
        }

        public bool IsMyPartyRaidMember(WoWUnit u)
        {
            if (u == null || !u.IsValid)
            {
                return false;
            }

            if (u.IsPet || u.IsTotem)
            {
                if (Me.PartyMembers.Contains(u.CreatedByUnit) || Me.RaidMembers.Contains(u.CreatedByUnit))
                {
                    return true;
                }
            }
            else if (u.IsPlayer)
            {
                if (Me.PartyMembers.Contains(u) || Me.RaidMembers.Contains(u))
                {
                    return true;
                }
            }

            return false;
        }

        #endregion

        #region IsMeorFocus

        public bool IsMeorFocus(WoWUnit target)
        {
            if (target == Me ||
                target == Me.FocusedUnit && ValidUnit(Me.FocusedUnit) && !IsEnemy(Me.FocusedUnit) ||
                target == Me.CurrentTarget && ValidUnit(Me.CurrentTarget) && !IsEnemy(Me.CurrentTarget) ||
                Me.CurrentMap.IsArena)
            {
                return true;
            }
            return false;
        }

        #endregion

        #region MeIsTank

        public static bool MeIsTank
        {
            get
            {
                //return (StyxWoW.Me.Role & WoWPartyMember.GroupRole.Tank) != 0 ||
                //        Tanks.All(t => !t.IsAlive) && StyxWoW.Me.HasAura("Bear Form");
                return (StyxWoW.Me.Role & WoWPartyMember.GroupRole.Tank) != 0;
            }
        }

        #endregion

        #region MyAura

        public bool MyAura(string auraName, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return false;

                bool aura = u.GetAllAuras().Any(a => a.Name == auraName && a.CreatorGuid == Me.Guid);

                return aura;
                //return u.ActiveAuras.Any(a => a.Value.Name == auraName && a.Value.CreatorGuid == Me.Guid);
            }
        }


        public bool MyAura(int auraID, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return false;

                bool aura = u.GetAllAuras().Any(a => a.SpellId == auraID && a.CreatorGuid == Me.Guid);

                return aura;

                //return u.ActiveAuras.Any(a => a.Value.SpellId == auraID && a.Value.CreatorGuid == Me.Guid);
            }
        }

        #endregion

        #region MyAuraTimeLeft

        public double MyAuraTimeLeft(string auraName, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        public double MyAuraTimeLeft(int auraID, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region SafelyFacingTarget

        public void SafelyFacingTarget(WoWUnit unit)
        {
            if (unit == null)
            {
                return;
            }

            if (!Me.IsMoving && !Me.IsSafelyFacing(unit) && THSettings.Instance.FaceAuto)
            {
                unit.Face();
            }
        }

        #endregion

        #region UnitAuraTimeLeft

        public double UnitAuraTimeLeft(string auraName, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        public double UnitAuraTimeLeft(int auraID, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
        }

        #endregion

        #region MyAuraStackCount

        public double MyAuraStackCount(string auraName, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.Name == auraName && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
        }

        public double MyAuraStackCount(int auraID, WoWUnit u)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (u == null || !u.IsValid || !u.IsAlive)
                    return 0;

                WoWAura aura = u.GetAllAuras().FirstOrDefault(a => a.SpellId == auraID && a.CreatorGuid == u.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
        }

        #endregion

        #region TalentSort

        public byte TalentSort(WoWUnit target)
        {
            if (target == null)
            {
                return 0;
            }

            if (target.Class == WoWClass.DeathKnight)
            {
                return 1;
            }

            if (target.Class == WoWClass.Druid)
            {
                if (target.Buffs.ContainsKey("Moonkin Form"))
                    return 3;
                if ((target.Buffs.ContainsKey("Leader of the Pack") &&
                     target.Buffs["Leader of the Pack"].CreatorGuid == target.Guid) || target.MaxMana < 40000)
                    return 1;
                return 4;
            }

            if (target.Class == WoWClass.Hunter)
            {
                return 2;
            }

            if (target.Class == WoWClass.Mage)
            {
                return 3;
            }

            if (target.Class == WoWClass.Paladin)
            {
                if (target.MaxMana >= 80000)
                    return 4;
                return 1;
            }

            if (target.Class == WoWClass.Priest)
            {
                if (target.HasAura("Shadowform"))
                    return 3;
                return 4;
            }

            if (target.Class == WoWClass.Rogue)
            {
                return 1;
            }

            if (target.Class == WoWClass.Shaman)
            {
                if (target.MaxMana < 40000)
                    return 1;
                if (target.Buffs.ContainsKey("Elemental Oath") &&
                    target.Buffs["Elemental Oath"].CreatorGuid == target.Guid)
                    return 3;
                return 4;
            }

            if (target.Class == WoWClass.Warlock)
            {
                return 3;
            }

            if (target.Class == WoWClass.Warrior)
            {
                return 1;
            }

            return 0;
        }

        public byte TalentSortSimple(WoWUnit target)
        {
            byte sortSimple = TalentSort(target);

            if (sortSimple == 4)
            {
                return 4;
            }

            if (sortSimple < 4 && sortSimple > 0)
            {
                return 1;
            }

            return 0;
        }

        #endregion

        #region UpdateMyLatency

        public static double MyLatency;

        public void UpdateMyLatency()
        {
            //If SLagTolerance enabled, start casting next spell MyLatency Millisecond before GlobalCooldown ready.

            MyLatency = (StyxWoW.WoWClient.Latency);

            //Use here because Lag Tolerance cap at 400
            //Logging.Write("----------------------------------");
            //Logging.Write("MyLatency: " + MyLatency);
            //Logging.Write("----------------------------------");

            if (MyLatency > 400)
            {
                //Lag Tolerance cap at 400
                MyLatency = 400;
            }
        }

        #endregion

        #region UpdateMyTalent

        public static string HasTalent = "";

        public void UpdateMyTalentEvent(object sender, LuaEventArgs args)
        {
            UpdateMyTalent();
        }

        public void UpdateMyTalent()
        {
            HasTalent = "";
            for (int i = 1; i <= 18; i++)
            {
                HasTalent = HasTalent +
                            Lua.GetReturnVal<String>(
                                string.Format(
                                    "local t= select(5,GetTalentInfo({0})) if t == true then return '['..select(1,GetTalentInfo({0}))..'] ' end return nil",
                                    i), 0);
            }

            Logging.Write("----------------------------------");
            Logging.Write("Talent:");
            Logging.Write(HasTalent);
            Logging.Write("----------------------------------");
        }

        #endregion

        #region UpdateMyGlyph

        // [Glyph of Beacon of Light] [Glyph of Harsh Words]
        public static string HasGlyph = "";

        public static string NoGCDSpells =
            "[Fortifying Brew] [Spear Hand Strike] [Invoke Xuen, the White Tiger] [Roll] [Clash] [Provoke] [Leer of the Ox] [Purifying Brew] [Elusive Brew] [Tigereye Brew] [Energizing Brew] [Chi Torpedo] [Energy Brew] [Zen Meditation]";


        public void UpdateMyGlyphEvent(object sender, LuaEventArgs args)
        {
            UpdateMyGlyph();
        }

        public void UpdateMyGlyph()
        {
            HasGlyph = "";
            var glyphCount = Lua.GetReturnVal<int>("return GetNumGlyphSockets()", 0);

            if (glyphCount != 0)
            {
                for (int i = 1; i <= glyphCount; i++)
                {
                    string lua =
                        String.Format(
                            "local enabled, glyphType, glyphTooltipIndex, glyphSpellID, icon = GetGlyphSocketInfo({0});if (enabled) then return glyphSpellID else return 0 end",
                            i);

                    var glyphSpellId = Lua.GetReturnVal<int>(lua, 0);

                    try
                    {
                        if (glyphSpellId > 0)
                        {
                            HasGlyph = HasGlyph + "[" + (WoWSpell.FromId(glyphSpellId)) + "] ";
                        }
                        else
                        {
                            Logging.Write("Glyphdetection - No Glyph in slot " + i);
                            //TreeRoot.Stop();
                        }
                    }
                    catch (Exception ex)
                    {
                        Logging.Write("We couldn't detect your Glyphs");
                        Logging.Write("Report this message to us: " + ex);
                        //TreeRoot.Stop();
                    }
                }
            }

            Logging.Write("----------------------------------");
            Logging.Write("Glyph:");
            Logging.Write(HasGlyph);
            Logging.Write("----------------------------------");
        }

        #endregion

        #region ValidUnit

        public bool ValidUnit(WoWUnit u)
        {
            if (u == null || !u.IsValid || !u.Attackable || !u.IsAlive || !u.CanSelect ||
                u.IsCritter && (u.CurrentTarget == null || u.CurrentTarget != null && u.CurrentTarget != Me) ||
                u.IsNonCombatPet || Blacklist.Contains(u.Guid, BlacklistFlags.All))
            {
                return false;
            }
            return true;
        }

        #endregion
    }
}